﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using MS_UI;

namespace SokectHelper
{
    public enum AppState
    {
        Starting, Stoped, Error, Connection
    }
    public class NetClient
    {
        public delegate void SocketDelegate(string msgStr);
        public delegate void SocketDelegate2(byte[] buffer);
        public delegate void SocketDelegate3(  int index,string msgStr);

        public event SocketDelegate RcvDoneEvent;
        public event SocketDelegate2 RcvDoneEvent2;
        public event SocketDelegate3 LogEvent;

        /// <summary>
        /// 单次接收有效
        /// </summary>
        private bool OneReceiveFlag = false;
        private int RcvLen = 0;
        //IP地址和端口号（用于服务器端）
        private IPEndPoint ServerInfo;
        //客户端运行的Socket
        private Socket ClientSocket;

        //接收缓冲区大小
        private Byte[] MsgReceiveBuffer;
        //发送缓冲区大小
        private Byte[] MsgSendBuffer;
        private AppState netState;
        public AppState NetState { get { return netState; } }
        //System.Timers.Timer wTime = new System.Timers.Timer(10);//间隔10mS定时器
        private int curTime = 0;
        public NetClient()
        {
            //客户端所使用的套接字对象
            MsgReceiveBuffer = new Byte[65535];
            MsgSendBuffer = new Byte[65535];
            netState = AppState.Stoped;
            //wTime.Elapsed += wTime_Elapsed;
            //wTime.AutoReset = true;
            //wTime.Enabled = true;

        }

        void wTime_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            curTime++;
        }
        public void Connect(string remoteIp, Int32 remotePort) 
        {
            if (netState != AppState.Connection)
            {
                ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //实例化一个IP地址和端口号（用于服务器端）
                ServerInfo = new IPEndPoint(IPAddress.Parse(remoteIp), remotePort);
                try
                {
                    netState = AppState.Starting;
                    //通过“套接字”“根据IP地址和端口号”连接服务器
                    ClientSocket.Connect(ServerInfo);


          
               


                    netState = AppState.Connection;
                    //从服务器端异步接收返回的消息（通过“ReceiveCallBack”方法异步接收消息）
                    ClientSocket.BeginReceive(MsgReceiveBuffer, 0, MsgReceiveBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
                    if (LogEvent != null)
                    {
                        LogEvent(1,string.Format("$Connect OK -> {0}", ServerInfo.ToString()));
                    }
                }
                catch (Exception ex)
                {
                    netState = AppState.Stoped;
                    if (LogEvent != null)
                    {
                        LogEvent(1,string.Format("$Connect Err01 -> ({0}:{1})", ServerInfo.ToString(), ex.Message));
                    }

                    throw ex;
                }
            }
        }


        private void ReceiveCallBack(IAsyncResult AR)
        {
            if (netState != AppState.Connection) return;
            try
            {
                //结束接收（返回接收数据的大小）
                int REnd = ClientSocket.EndReceive(AR);
                //MessageBox.Show(REnd.ToString());
                if (REnd == 0)
                {

                CommMethods.EAPIsConnected = false;
                netState = AppState.Stoped;
                    //  ClientSocket.Shutdown(SocketShutdown.Both);
                    Thread.Sleep(10);
                    // ClientSocket.Disconnect(false);
                    ClientSocket.Close();
                    ClientSocket = null;
                    if (LogEvent != null)
                    {
                        LogEvent(1,string.Format("$Connect Err02 -> ({0}:{1})", ServerInfo.ToString(), "Server Off"));

                        StopConnect();

                    }
                    return;
                }
                OneReceiveFlag = false;
                RcvLen = REnd;
                //显示所接收的消息
                //this.RecieveMsg.AppendText(Encoding.Unicode.GetString(MsgReceiveBuffer, 0, REnd));
                //触发事件
                if (RcvDoneEvent != null)
                    RcvDoneEvent(Encoding.Default.GetString(MsgReceiveBuffer, 0, REnd));

                byte[] buff = new byte[REnd];
                //Buffer.BlockCopy(state.Buffer, 0, buff, 0, rcvLen);
                Array.Copy(MsgReceiveBuffer, 0, buff, 0, REnd);

                RcvDoneEvent2(buff);



                if (LogEvent != null)
                {
              //      LogEvent(1,string.Format("$ON Receive -> ({0}:{1})", ServerInfo.ToString(), Encoding.Unicode.GetString(buff, 0, REnd)));
              



                }
                WriteErrorLog("接收到信息，字符串内容---" + Encoding.Default.GetString(MsgReceiveBuffer, 0, REnd));
                //再次开始异步接收
                ClientSocket.BeginReceive(MsgReceiveBuffer, 0, MsgReceiveBuffer.Length, 0, new AsyncCallback(ReceiveCallBack), null);
            }
            catch (Exception ex)
            {
                if (LogEvent != null)
                {
                    LogEvent(1,string.Format("$Connect Err03 -> ({0}:{1})", ServerInfo.ToString(), ex.Message));
                    CommMethods.EAPIsConnected = false;
                    StopConnect();
                }
                //MessageBox.Show("已经与服务器断开连接！");
                WriteErrorLog("已经与服务器断开连接！");
            }

        }
        public void StopConnect()
        {
            if (netState == AppState.Connection && ClientSocket != null)
            {
                netState = AppState.Stoped;
                //ClientSocket.Send(Encoding.Unicode.GetBytes(this.txtNickName.Text + "离开了房间！\n"));
                //ClientSocket.Shutdown(SocketShutdown.Both);
                Thread.Sleep(10);
                // ClientSocket.Disconnect(false);
                ClientSocket.Close();
                ClientSocket = null;
                if (LogEvent != null)
                {
                    LogEvent(1,string.Format("$StopConnect OK -> {0}", ServerInfo.ToString()));
                }
            }


        }

        public void SendMsg(string sendMsg)
        {
            if (sendMsg.Length == 0 || (netState != AppState.Connection))
            {
                return;
            }
            //MsgSendBuffer = Encoding.Default.GetBytes(sendMsg);
            //如果已连接则发送消息
            if (ClientSocket.Connected)
            {
                //发送消息（同时异步调用“ReceiveCallBack”方法接收数据）
                ClientSocket.Send(Encoding.Default.GetBytes(sendMsg), 0, sendMsg.Length, 0);
                //Thread.Sleep(1000);
                WriteErrorLog("发送的字符串内容---" + sendMsg);
                if (LogEvent != null)
                {
                //    LogEvent(1,string.Format("$SendMsg OK -> {0}:{1}", ServerInfo.ToString(), sendMsg));
                }
            }
            else
            {
                netState = AppState.Stoped;
                WriteErrorLog("当前与服务器断开连接,无法发送信息！");
                if (LogEvent != null)
                {
                    LogEvent(1,string.Format("$SendMsg Err -> {0}:{1}", ServerInfo.ToString(), "Connect Err "));
                }
            }
        }
         
        public void SendByteMsg(byte[] sendbuffer)
        {
            if (sendbuffer.Length == 0 || (netState != AppState.Connection))
            {
                return;
            }
            //MsgSendBuffer = Encoding.Default.GetBytes(sendMsg);
            //如果已连接则发送消息
            if (ClientSocket.Connected)
            {
                //发送消息（同时异步调用“ReceiveCallBack”方法接收数据）
                ClientSocket.Send(sendbuffer, 0, sendbuffer.Length, 0);
                //Thread.Sleep(1000);
                WriteErrorLog("发送的字符串内容---" + Encoding.Default.GetString(sendbuffer));
                if (LogEvent != null)
                {
                  //  LogEvent(1,string.Format("$SendMsg OK -> {0}:{1}", ServerInfo.ToString(), Encoding.Unicode.GetString(sendbuffer)));
                }
            }
            else
            {
                netState = AppState.Stoped;
                WriteErrorLog("当前与服务器断开连接,无法发送信息！");
                if (LogEvent != null)
                {
                    LogEvent(1,string.Format("$SendMsg Err -> {0}:{1}", ServerInfo.ToString(), "Connect Err "));
                }
            }
        }





        public int SendCommand(byte[] SendData, ref  byte[] ReceiveData, int Overtime)
        {
            if (SendData.Length == 0 || (netState != AppState.Connection))
            {
                return -1;
            }
            OneReceiveFlag = true;
            bool rcvOk = false;
            //  OneSendOk = false;
            curTime = 0;
            RcvLen = 0;
            int ret = 0;
            if (ClientSocket.Connected)
            {
                //发送消息（同时异步调用“ReceiveCallBack”方法接收数据）
                ClientSocket.Send(SendData, 0, SendData.Length, 0);
                //ClientSocket.BeginSend(SendData, 0, SendData.Length, SocketFlags.None, new AsyncCallback(SendCallBack), null);
                string sendMsg = Encoding.Default.GetString(SendData, 0, SendData.Length);
                //Thread.Sleep(1000);
                if (LogEvent != null)
                {
                    LogEvent(1,string.Format("$SendMsg OK -> {0}:{1}", ServerInfo.ToString(), sendMsg));
                }
                Thread objThread = new Thread(() =>
                {
                    while (curTime++ < Overtime)
                    {
                        if (!OneReceiveFlag)
                        {
                            break;
                        }
                        Thread.Sleep(200);
                    }
                 
                    rcvOk = true;
              
                });
                objThread.IsBackground = true;
                objThread.Start();

                while (true)
                {
                    if (rcvOk)
                    {    
                        if (!OneReceiveFlag)
                        {
                            ret = RcvLen;
                            ReceiveData = new byte[RcvLen];
                            Array.Copy(MsgReceiveBuffer, 0, ReceiveData, 0, RcvLen);
                        }
       

                        break;
                    }
                    
                }
               
                //ret = ClientSocket.Receive(MsgReceiveBuffer, 0, MsgReceiveBuffer.Length, SocketFlags.None);
            }
            else
            {
                netState = AppState.Stoped;
                WriteErrorLog("当前与服务器断开连接,无法发送信息！");
                if (LogEvent != null)
                {
                    LogEvent(1,string.Format("$SendMsg Err -> {0}:{1}", ServerInfo.ToString(), "Connect Err "));
                }
            }
       
            return ret;
        }

        private void SendCallBack(IAsyncResult AR)
        {
            if (netState != AppState.Connection) return;
            //结束接收（返回接收数据的大小）
            ClientSocket.EndSend(AR);
        }

        private static object lockobject = new object();



        private static void WriteErrorLog(string msg)
        {
            lock (lockobject)
            {
            string fileName = "SokectClientLog " + DateTime.Now.ToString("yyyy-MM-dd") + ".TXT";
            FileStream fs = new FileStream(fileName, FileMode.Append);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine("[" + DateTime.Now.ToString() + "] 日志内容：" + msg);
            sw.Close();
            fs.Close();
        }
        }
    }
}
